﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Flagwind.Data
{
	public class Command<T> where T : class, IEntity, new()
	{
		protected internal Command currentCommand;
		private T currentEntity;
		private DataAccess _dataAccess = new DataAccess();

		public delegate object[] SelectFieldFunc(T s);

		public Command(Command command, T entity)
		{
			this.currentCommand = command;
			this.currentEntity = entity;
		}

		public Command1<T> Select()
		{
			return new Command1<T>(this, currentCommand.Select());
		}

		public Command1<T> Select(SelectFieldFunc func)
		{
			return new Command1<T>(this, currentCommand.Select(func(currentEntity)));
		}

		/// <summary>
		/// 以每页不超过 pageSize 条记录，查询第 pageNumber 页的数据
		/// </summary>
		/// <param name="pageSize">每页显示的记录数量</param>
		/// <param name="pageNumber">所在页页码，从1开始</param>
		/// <returns>GCommand对象</returns>
		public Command<T> Limit(int pageSize, int pageNumber)
		{
			this.currentCommand.Limit(pageSize, pageNumber);
			return this;
		}

		/// <summary>
		/// 以每页不超过 pageSize 条记录，查询第 pageNumber 页的数据。如果没有指定排序方法，可以不指定记录总数，
		/// 但不可指定为0，或者使用另外一个重载。
		/// </summary>
		/// <param name="pageSize">每页显示的记录数量</param>
		/// <param name="pageNumber">所在页页码，从1开始</param>
		/// <param name="allCount">记录总数</param>
		/// <returns></returns>
		public Command<T> Limit(int pageSize, int pageNumber, int allCount)
		{
			this.currentCommand.RecordCount = allCount;
			this.currentCommand.Limit(pageSize, pageNumber);
			return this;
		}

		public Command<T> Print(out string sqlInfo)
		{
			sqlInfo = string.Format("SQL:{0}\r\n{1}", currentCommand.ToString(), currentCommand.PrintParameterInfo());
			return this;
		}

		/// <summary>
		/// 提供查询的锁限定(注意:只支持SQLSERVER)(注:本方法由网友 唔 提供)
		/// </summary>
		/// <param name="lockname"></param>
		/// <returns></returns>
		public Command<T> With(Command.SqlServerLock lockname)
		{
			currentCommand.With(lockname);
			return this;
		}

		public List<T> ToList(IDataProvider db)
		{
			return _dataAccess.Select<T>(this.currentCommand, db).ToList();
		}

		/// <summary>
		/// 将查询结果映射到另外的具有同名属性的类型，比如DTO对象
		/// </summary>
		/// <typeparam name="T1">DTO对象的类型</typeparam>
		/// <param name="db">IDataProvider</param>
		/// <returns>DTO对象列表</returns>
		public List<T1> MapToPOCOList<T1>(IDataProvider db) where T1 : class, new()
		{
			List<T> list = _dataAccess.Select<T>(this.currentCommand, db).ToList();
			List<T1> dtoList = new List<T1>();
			foreach(var item in list)
			{
				T1 dto = new T1();
				IEntity entity = item as IEntity;
				if(entity != null)
				{
					entity.MapTo(dto); //实体类到dto的映射
				}
				dtoList.Add(dto);
			}
			return dtoList;
		}

		public List<T> ToList()
		{
			return ToList(DataProviderFactory.DefaultProvider);
		}

		public T ToObject(IDataProvider db)
		{
			return _dataAccess.Find<T>(this.currentCommand, db);
		}

		public T ToObject()
		{
			return ToObject(DataProviderFactory.DefaultProvider);
		}

		override public string ToString()
		{
			return currentCommand.ToString();
		}

		public Command End()
		{
			return this.currentCommand;
		}
	}

	public class Command1<T> : Command2<T> where T : class, IEntity, new()
	{
		private Command<T> currentGCommand;
		private Command1 currentCommand1;

		public Command1(Command<T> gq, Command1 q1) : base(gq)
		{
			this.currentGCommand = gq;
			this.currentCommand1 = q1;
		}

		public Command2<T> Where(CompareFunc<T> func)
		{
			this.currentCommand1.Where(func);
			return new Command2<T>(currentGCommand);
		}
	}

	public class Command2<T> where T : class, IEntity, new()
	{
		private Command<T> currentGCommand;

		public Command2(Command<T> gq)
		{
			this.currentGCommand = gq;
		}

		public Command<T> OrderBy(OrderAction<T> orderAct)
		{
			Command4 currentCommand4 = new Command4(this.currentGCommand.currentCommand).OrderBy<T>(orderAct);
			return this.currentGCommand;
		}

		public Command<T> End()
		{
			return this.currentGCommand;
		}
	}
}